package com.gitee.mrj.aiboot.core.sf.generators.type;

import com.fasterxml.jackson.databind.node.ObjectNode;
import com.gitee.mrj.aiboot.annotation.config.sf.type.AlainField;
import com.gitee.mrj.aiboot.core.sf.generators.FormDefinitionGenerator;
import com.gitee.mrj.aiboot.core.sf.generators.UIForm;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.TypeUtils;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.time.temporal.TemporalAccessor;
import java.util.Collection;
import java.util.Date;

@Component
public class AlainFieldGenerator implements FormDefinitionGenerator {
    @Override
    public void generate(UIForm root, Field field, UIForm node) {
        AlainField alainField = AnnotatedElementUtils.findMergedAnnotation(field, AlainField.class);
        ObjectNode definition = node.getSchema();
        ObjectNode ui = node.getUi();
        if (alainField.required()) {
            required(root.getSchema()).add(field.getName());
        }
        definition.put("title", alainField.title());
        if (StringUtils.isNotBlank(alainField.description())) {
            definition.put("description", alainField.description());
        }
        if (alainField.readOnly()) {
            definition.put("readOnly", alainField.readOnly());
        }


        // 自动推测字段类型
        Class<?> type = field.getType();
        if (TypeUtils.isAssignable(CharSequence.class, type)
                || TypeUtils.isAssignable(TemporalAccessor.class, type)
                || TypeUtils.isAssignable(Date.class, type)) {
            definition.put("type", SFSchemaType.STRING.toString());
            ui.put("widget", SFSchemaType.STRING.toString());
        } else if (TypeUtils.isAssignable(Integer.class, type)
                || TypeUtils.isAssignable(Short.class, type)
                || TypeUtils.isAssignable(Byte.class, type)) {
            definition.put("type", SFSchemaType.INTEGER.toString());
            ui.put("widget", SFSchemaType.INTEGER.toString());
        } else if (TypeUtils.isAssignable(Number.class, type)) {
            definition.put("type", SFSchemaType.NUMBER.toString());
            ui.put("widget", SFSchemaType.NUMBER.toString());
        } else if (TypeUtils.isAssignable(Boolean.class, type)) {
            definition.put("type", SFSchemaType.BOOLEAN.toString());
            ui.put("widget", SFSchemaType.BOOLEAN.toString());
        } else if (type.isArray()
                || TypeUtils.isAssignable(Array.class, type)
                || TypeUtils.isAssignable(Collection.class, type)) {
            definition.put("type", SFSchemaType.ARRAY.toString());
            ui.put("widget", SFSchemaType.ARRAY.toString());
        } else {
            definition.put("type", SFSchemaType.STRING.toString());
            ui.put("widget", SFSchemaType.STRING.toString());
        }
    }


    @Override
    public Class[] supports() {
        return new Class[]{AlainField.class};
    }
}
